package net.cgsoft.widget.https.okhttp;

import android.content.Context;
import android.os.Handler;
import android.util.Log;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;


import net.cgsoft.widget.R;
import net.cgsoft.widget.https.HttpCallBack;
import net.cgsoft.widget.model.Model;
import net.cgsoft.widget.utils.Util;

import java.io.IOException;

import java.util.HashMap;
import java.util.UUID;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.FormBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;


/**
 * Created by Youga on 2015/9/19.
 */
public abstract class BaseRequest {

    protected final String TAG = getClass().getSimpleName();
    protected final Handler mDelivery;
    protected final OkHttpClient mOkHttpClient;
    protected final Gson mGson;
    protected Context mContext;
    protected String noInternet, genericError, dataError;

    protected BaseRequest(Context context) {
        mContext = context;
        OkHttpUtil okHttpUtil = OkHttpUtil.getInstance();
        mDelivery = okHttpUtil.getDelivery();
        mOkHttpClient = okHttpUtil.getOkHttpClient();
        mGson = okHttpUtil.getGson();
        noInternet = context.getString(R.string.no_internet);
        genericError = context.getString(R.string.generic_error);
        dataError = context.getString(R.string.server_data_error);
    }

    protected boolean checkNetworkState(Runnable runnable) {
        if (!Util.checkNetworkState(mContext)) {
            mDelivery.postDelayed(runnable, 1000);
            return false;
        } else {
            return true;
        }
    }

    protected void postRunnable(Runnable runnable) {
        mDelivery.post(runnable);
    }

    protected void printlnUrl(String url, FormBody formBody) {
        Log.i("URL", url);
        if (formBody != null) {
            StringBuilder builder = new StringBuilder();
            for (int i = 0; i < formBody.size(); i++) {
                builder.append(formBody.name(i) + "=" + formBody.value(i) + "&");
            }
            if (builder.lastIndexOf("&") != -1) {
                builder.delete(builder.lastIndexOf("&"), builder.length());
            }
            Log.w("PARAMS", builder.toString());
        }
    }

    protected abstract void appendHeader(FormBody.Builder formBuilder);

    protected abstract void appendPageHeader(FormBody.Builder formBuilder);

    protected abstract void sendAlertCallback(Context context, String message);

    public <T> void function(String url, HashMap<String, String> params,
                             final TypeToken<Model<T>> typeToken, final HttpCallBack<T> callBack) {
        //检查网络
        if (!checkNetworkState(new Runnable() {
            @Override
            public void run() {
                callBack.onFailure(noInternet);
            }
        })) return;

        callBack.onStart();
        FormBody.Builder formBuilder = new FormBody.Builder();
        if (params == null) params = new HashMap<>();
        for (String key : params.keySet()) {
            formBuilder.add(key, params.get(key));
        }

        appendHeader(formBuilder);

        final String uuid = UUID.randomUUID().toString();
        Request request = new Request.Builder()
                .url(url)
                .post(formBuilder.build())
                .tag(uuid)
                .build();

        mOkHttpClient.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, final IOException e) {
                String tag = (String) call.request().tag();
                if (!uuid.equals(tag)) return;
                postRunnable(new Runnable() {
                    @Override
                    public void run() {
                        callBack.onFinish();
                        callBack.onFailure(genericError);
                    }
                });
            }

            @Override
            public void onResponse(Call call, Response response) {
                String tag = (String) call.request().tag();
                if (!uuid.equals(tag)) return;
                try {
                    String json = response.body().string();
                    final Model<T> model = mGson.fromJson(json, typeToken.getType());
                    switch (model.getCode()) {
                        case 99:
                            postRunnable(new Runnable() {
                                @Override
                                public void run() {
                                    callBack.onFinish();
                                    sendAlertCallback(mContext, model.getMessage());
                                }
                            });
                            break;
                        case 0:
                            postRunnable(new Runnable() {
                                @Override
                                public void run() {
                                    callBack.onFinish();
                                    callBack.onSuccess(model);
                                }
                            });
                            break;
                        default:
                            postRunnable(new Runnable() {
                                @Override
                                public void run() {
                                    callBack.onFinish();
                                    callBack.onFailure(model.getMessage());
                                }
                            });
                            break;
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    postRunnable(new Runnable() {
                        @Override
                        public void run() {
                            callBack.onFinish();
                            callBack.onFailure(dataError);
                        }
                    });
                }
            }
        });

        printlnUrl(url, formBuilder.build());
    }
}
